package zasm.zasm.listing;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import zasm.zasm.util.SingletonIterator;

public abstract class AbstractListingWriter implements ListingWriter {

	private final List<String>	fileStack		= new ArrayList<>();
	private final List<Integer>	lineNumberStack	= new ArrayList<>();
	private int					lineNumber;
	private int					origin			= -1;

	public AbstractListingWriter() {}

	@Override
	public void pushFile(final String filename) {
		fileStack.add(filename);
		lineNumberStack.add(lineNumber);
		lineNumber = 1;
	}

	@Override
	public void popFile() {
		fileStack.remove(fileStack.size() - 1);
		lineNumber = lineNumberStack.remove(lineNumberStack.size() - 1);
	}

	protected int getFileDepth() {
		return fileStack.size();
	}

	@Override
	public void setLineNumber(final int lineNumber) {
		this.lineNumber = lineNumber;
	}

	protected int getLineNumber() {
		return lineNumber;
	}

	@Override
	public void setOrigin(final int origin) {
		this.origin = origin;
	}

	protected int getOrigin() {
		return origin;
	}

	@Override
	public final void write(final String in, final byte[] out) throws IOException {
		write(new SingletonIterator<>(in), out);
	}

	@Override
	public final void write(final Iterable<String> in, final byte[] out) throws IOException {
		write(in.iterator(), out);
	}

	@Override
	public final void write(final Iterator<String> in, final byte[] out) throws IOException {
		if (fileStack.size() == 0) {
			throw new IllegalStateException("Cannot write to listing file: no input file context");
		}
		writeInternal(in, out);
		lineNumber++;
		origin += out.length;
	}

	protected abstract void writeInternal(Iterator<String> in, byte[] out) throws IOException;

}
